#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""属性编辑器组件"""

from PyQt5.QtWidgets import (
    QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem,
    QLineEdit, QComboBox, QCheckBox, QSpinBox, QDoubleSpinBox,
    QLabel, QGroupBox, QGridLayout, QScrollArea, QMessageBox
)
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QFont, QColor, QBrush


class PropertyEditor(QWidget):
    """属性编辑器组件"""
    
    # 属性改变信号
    property_changed = pyqtSignal(str, str, object)  # (component_name, property_name, new_value)
    
    def __init__(self, parent=None):
        """初始化属性编辑器"""
        super().__init__(parent)
        
        # 设置窗口属性
        self.setWindowTitle("属性编辑器")
        self.setMinimumWidth(200)
        
        # 当前选中的组件
        self.current_component = None
        
        # 创建主布局
        main_layout = QVBoxLayout(self)
        
        # 创建属性树
        self.property_tree = QTreeWidget()
        self.property_tree.setHeaderLabels(["属性", "值"])
        self.property_tree.setColumnWidth(0, 100)
        self.property_tree.setColumnWidth(1, 100)
        self.property_tree.setAlternatingRowColors(True)
        
        # 添加到主布局
        main_layout.addWidget(self.property_tree)
        
        # 设置信号和槽
        self.setup_connections()
    
    def setup_connections(self):
        """设置信号和槽的连接"""
        # 连接项双击信号
        self.property_tree.itemDoubleClicked.connect(self.on_item_double_clicked)
    
    def set_component(self, component, properties=None):
        """设置当前要编辑的组件"""
        self.current_component = component
        
        # 清空属性树
        self.property_tree.clear()
        
        if component is None:
            return
        
        # 如果没有提供属性，获取组件的所有属性
        if properties is None:
            properties = self.get_component_properties(component)
        
        # 按类别组织属性
        categories = self.organize_properties_by_category(properties)
        
        # 填充属性树
        for category, props in categories.items():
            # 创建分类节点
            category_item = QTreeWidgetItem([category])
            category_item.setFlags(category_item.flags() & ~Qt.ItemIsEditable)
            category_item.setForeground(0, QBrush(QColor(0, 0, 128)))
            
            # 添加属性项
            for prop_name, prop_value in props.items():
                self.add_property_item(category_item, prop_name, prop_value)
            
            # 添加到树中
            self.property_tree.addTopLevelItem(category_item)
            category_item.setExpanded(True)
    
    def organize_properties_by_category(self, properties):
        """按类别组织属性"""
        categories = {
            "基本": {},
            "外观": {},
            "布局": {},
            "行为": {}
        }
        
        # 根据属性名称分配到不同的类别
        for prop_name, prop_value in properties.items():
            if prop_name in ['objectName', 'enabled', 'visible']:
                categories["基本"][prop_name] = prop_value
            elif prop_name in ['text', 'font', 'color', 'styleSheet']:
                categories["外观"][prop_name] = prop_value
            elif prop_name in ['geometry', 'minimumSize', 'maximumSize', 'sizePolicy']:
                categories["布局"][prop_name] = prop_value
            else:
                # 默认添加到行为类别
                categories["行为"][prop_name] = prop_value
        
        # 移除空类别
        return {k: v for k, v in categories.items() if v}
    
    def add_property_item(self, parent_item, prop_name, prop_value):
        """添加属性项到树中"""
        # 创建属性项
        item = QTreeWidgetItem([prop_name, self.format_property_value(prop_value)])
        
        # 存储原始属性值
        item.setData(1, Qt.UserRole, prop_value)
        
        # 设置是否可编辑
        if isinstance(prop_value, bool):
            # 布尔值不可直接编辑，需要双击弹出复选框
            item.setFlags(item.flags() & ~Qt.ItemIsEditable)
        else:
            # 其他类型可以编辑
            item.setFlags(item.flags() | Qt.ItemIsEditable)
        
        # 添加到父项
        parent_item.addChild(item)
    
    def format_property_value(self, value):
        """格式化属性值以显示"""
        if value is None:
            return "None"
        elif isinstance(value, bool):
            return "True" if value else "False"
        elif hasattr(value, '__str__'):
            # 对于复杂对象，只显示类名
            if hasattr(value, '__class__'):
                if str(value) != value.__class__.__name__:
                    return f"{value.__class__.__name__}({str(value)})"
                return value.__class__.__name__
            return str(value)
        return ""
    
    def on_item_double_clicked(self, item, column):
        """处理项目双击事件"""
        if column != 1:  # 只处理值列
            return
        
        # 获取属性名和当前值
        prop_name = item.text(0)
        current_value = item.data(1, Qt.UserRole)
        
        # 根据属性类型显示不同的编辑器
        if isinstance(current_value, bool):
            # 布尔值使用复选框
            self.show_boolean_editor(item, prop_name, current_value)
        elif isinstance(current_value, int):
            # 整数使用SpinBox
            self.show_integer_editor(item, prop_name, current_value)
        elif isinstance(current_value, float):
            # 浮点数使用DoubleSpinBox
            self.show_float_editor(item, prop_name, current_value)
        else:
            # 其他类型使用默认的编辑功能（双击进入编辑状态）
            pass
    
    def show_boolean_editor(self, item, prop_name, current_value):
        """显示布尔值编辑器"""
        # 创建复选框
        checkbox = QCheckBox()
        checkbox.setChecked(current_value)
        
        # 连接信号
        checkbox.stateChanged.connect(lambda state: self.on_boolean_value_changed(item, prop_name, state == Qt.Checked))
        
        # 设置编辑器
        self.property_tree.setItemWidget(item, 1, checkbox)
    
    def show_integer_editor(self, item, prop_name, current_value):
        """显示整数编辑器"""
        # 创建SpinBox
        spinbox = QSpinBox()
        spinbox.setRange(-2147483648, 2147483647)
        spinbox.setValue(current_value)
        
        # 连接信号
        spinbox.valueChanged.connect(lambda value: self.on_integer_value_changed(item, prop_name, value))
        
        # 设置编辑器
        self.property_tree.setItemWidget(item, 1, spinbox)
    
    def show_float_editor(self, item, prop_name, current_value):
        """显示浮点数编辑器"""
        # 创建DoubleSpinBox
        spinbox = QDoubleSpinBox()
        spinbox.setRange(-1e308, 1e308)
        spinbox.setDecimals(6)
        spinbox.setValue(current_value)
        
        # 连接信号
        spinbox.valueChanged.connect(lambda value: self.on_float_value_changed(item, prop_name, value))
        
        # 设置编辑器
        self.property_tree.setItemWidget(item, 1, spinbox)
    
    def on_boolean_value_changed(self, item, prop_name, new_value):
        """处理布尔值改变事件"""
        self.update_property_value(item, prop_name, new_value)
        
        # 移除编辑器控件
        self.property_tree.setItemWidget(item, 1, None)
        
        # 更新显示
        item.setText(1, "True" if new_value else "False")
    
    def on_integer_value_changed(self, item, prop_name, new_value):
        """处理整数值改变事件"""
        self.update_property_value(item, prop_name, new_value)
        
        # 移除编辑器控件
        self.property_tree.setItemWidget(item, 1, None)
        
        # 更新显示
        item.setText(1, str(new_value))
    
    def on_float_value_changed(self, item, prop_name, new_value):
        """处理浮点数值改变事件"""
        self.update_property_value(item, prop_name, new_value)
        
        # 移除编辑器控件
        self.property_tree.setItemWidget(item, 1, None)
        
        # 更新显示
        item.setText(1, str(new_value))
    
    def update_property_value(self, item, prop_name, new_value):
        """更新属性值"""
        if self.current_component is None:
            return
        
        # 尝试设置组件的属性
        try:
            # 根据属性名设置属性
            if prop_name == 'objectName':
                self.current_component.setObjectName(new_value)
            elif prop_name == 'text':
                if hasattr(self.current_component, 'setText'):
                    self.current_component.setText(new_value)
            elif prop_name == 'enabled':
                self.current_component.setEnabled(new_value)
            elif prop_name == 'geometry':
                # 这里需要处理几何属性的设置
                pass
            else:
                # 尝试直接设置属性
                if hasattr(self.current_component, prop_name):
                    setattr(self.current_component, prop_name, new_value)
                elif hasattr(self.current_component, f'set{prop_name[:1].upper()}{prop_name[1:]}'):
                    setattr(self.current_component, f'set{prop_name[:1].upper()}{prop_name[1:]}', new_value)
        except Exception as e:
            QMessageBox.warning(self, "警告", f"无法设置属性 '{prop_name}': {str(e)}")
            return
        
        # 更新项目数据
        item.setData(1, Qt.UserRole, new_value)
        
        # 发送属性改变信号
        component_name = self.current_component.objectName()
        self.property_changed.emit(component_name, prop_name, new_value)
    
    def get_component_properties(self, component):
        """获取组件的可编辑属性"""
        properties = {}
        
        # 基本属性
        properties['objectName'] = component.objectName()
        properties['enabled'] = component.isEnabled()
        properties['visible'] = component.isVisible()
        
        # 几何属性
        properties['geometry'] = component.geometry()
        properties['minimumSize'] = component.minimumSize()
        properties['maximumSize'] = component.maximumSize()
        properties['sizePolicy'] = component.sizePolicy()
        
        # 根据组件类型添加特定属性
        if isinstance(component, QPushButton):
            properties['text'] = component.text()
            properties['checkable'] = component.isCheckable()
            properties['checked'] = component.isChecked()
            properties['autoDefault'] = component.autoDefault()
            properties['default'] = component.isDefault()
        elif isinstance(component, QLabel):
            properties['text'] = component.text()
            properties['alignment'] = component.alignment()
            properties['wordWrap'] = component.wordWrap()
        elif isinstance(component, QLineEdit):
            properties['text'] = component.text()
            properties['placeholderText'] = component.placeholderText()
            properties['echoMode'] = component.echoMode()
            properties['readOnly'] = component.isReadOnly()
            properties['maxLength'] = component.maxLength()
        elif isinstance(component, QTextEdit):
            properties['plainText'] = component.toPlainText()
            properties['readOnly'] = component.isReadOnly()
        elif isinstance(component, QCheckBox):
            properties['text'] = component.text()
            properties['checked'] = component.isChecked()
            properties['tristate'] = component.isTristate()
        elif isinstance(component, QComboBox):
            properties['currentText'] = component.currentText()
            properties['currentIndex'] = component.currentIndex()
            properties['editable'] = component.isEditable()
        elif isinstance(component, QSpinBox):
            properties['value'] = component.value()
            properties['minimum'] = component.minimum()
            properties['maximum'] = component.maximum()
            properties['singleStep'] = component.singleStep()
        elif isinstance(component, QDoubleSpinBox):
            properties['value'] = component.value()
            properties['minimum'] = component.minimum()
            properties['maximum'] = component.maximum()
            properties['singleStep'] = component.singleStep()
            properties['decimals'] = component.decimals()
        
        return properties